home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
archiver
/
lzhsourc.lzh
/
LZH.SRC
/
LHUF5.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-02
|
23KB
|
962 lines
#include "lh5.h"
#include <stdlib.h>
#include <string.h> /* memmove() */
#ifdef __TOS__
#include "goodputc.h"
#endif
/* #define _lhufs_ */
extern uchar text_buf[DICSIZ];
#define buffer text_buf
/* static uchar buffer[DICSIZ]; */
#define CRCPOLY 0xA001 /* ANSI CRC-16 */
/* CCITT: 0x8408 */
#define UPDATE_CRC(c) \
crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT)
extern FILE *infile, *outfile;
extern uint crc;
ulong origsize,compsize;
#ifdef _lhufs_
uint bitbuf;
extern uint subbitbuf;
extern int bitcount;
extern ulong origsize,compsize;
#else
uint bitbuf;
uint subbitbuf;
int bitcount;
ulong origsize,compsize;
#endif
extern uchar flg_n;
ushort crctable[UCHAR_MAX + 1];
uint subbitbuf;
int bitcount;
static void error(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
putc('\n', stderr);
vfprintf(stderr, fmt, args);
putc('\n', stderr);
va_end(args);
exit(EXIT_FAILURE);
}
void make_crctable(void)
{
uint i, j, r;
static int crc_ready = 0;
if (crc_ready == 0) {
for (i = 0; i <= UCHAR_MAX; i++) {
r = i;
for (j = 0; j < CHAR_BIT; j++)
if (r & 1) r = (r >> 1) ^ CRCPOLY;
else r >>= 1;
crctable[i] = r;
}
crc_ready=1;
}
}
void fillbuf(int n) /* Shift bitbuf n bits left, read n bits */
{
bitbuf <<= n;
while (n > bitcount) {
bitbuf |= subbitbuf << (n -= bitcount);
if (compsize != 0) {
compsize--; subbitbuf = (uchar) getc(infile);
} else subbitbuf = 0;
bitcount = CHAR_BIT;
}
bitbuf |= subbitbuf >> (bitcount -= n);
}
static uint getbits(int n)
{
uint x;
x = bitbuf >> (BITBUFSIZ - n); fillbuf(n);
return x;
}
static void putbits(int n, uint x) /* Write rightmost n bits of x */
{
if (n < bitcount) {
subbitbuf |= x << (bitcount -= n);
} else {
if (compsize < origsize) {
if (putc(subbitbuf | (x >> (n -= bitcount)), outfile) == EOF) error("Unable to write");
compsize++;
} else unpackable = 1;
if (n < CHAR_BIT) {
subbitbuf = x << (bitcount = CHAR_BIT - n);
} else {
if (compsize < origsize) {
if (putc(x >> (n - CHAR_BIT), outfile) == EOF) error("Unable to write");
compsize++;
} else unpackable = 1;
subbitbuf = x << (bitcount = 2 * CHAR_BIT - n);
}
}
}
int fread_crc(uchar *p, int n, FILE *f)
{
int i;
i = n = fread(p, 1, n, f); origsize += n;
while (--i >= 0) UPDATE_CRC(*p++);
return n;
}
static void fwrite_crc(uchar *p, int n, FILE *f)
{
if (f!= NULL) if (fwrite(p, 1, n, f) < n) error("Unable to write");
while (--n >= 0) UPDATE_CRC(*p++);
}
static void init_getbits(void)
{
bitbuf = 0; subbitbuf = 0; bitcount = 0;
fillbuf(BITBUFSIZ);
}
static void init_putbits(void)
{
bitcount = CHAR_BIT; subbitbuf = 0;
}
/* --------------------------- End of IO.C --------------------------- */
/***********************************************************
decode.c
***********************************************************/
/* ----------------------Start of huf.c ------------------------------- */
/***********************************************************
huf.c -- static Huffman
***********************************************************/
#define NP (DICBIT + 1)
#define NT (CODE_BIT + 3)
#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */
#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */
#if NT > NP
#define NPT NT
#else
#define NPT NP
#endif
extern ushort left[2 * NC - 1], right[2 * NC - 1];
extern uchar *buf, c_len[NC], pt_len[NPT];
extern int bufsiz = 0, blocksize;
extern ushort c_freq[2 * NC - 1], c_table[4096], c_code[NC],
p_freq[2 * NP - 1], pt_table[256], pt_code[NPT],
t_freq[2 * NT - 1];
extern ushort dad[4096];
#define c_table dad
/***** encoding *****/
void count_t_freq(void)
{
int i, k, n, count;
for (i = 0; i < NT; i++) t_freq[i] = 0;
n = NC;
while (n > 0 && c_len[n - 1] == 0) n--;
i = 0;
while (i < n) {
k = c_len[i++];
if (k == 0) {
count = 1;
while (i < n && c_len[i] == 0) { i++; count++; }
if (count <= 2) t_freq[0] += count;
else if (count <= 18) t_freq[1]++;
else if (count == 19) { t_freq[0]++; t_freq[1]++; }
else t_freq[2]++;
} else t_freq[k + 2]++;
}
}
void write_pt_len(int n, int nbit, int i_special)
{
int i, k;
while (n > 0 && pt_len[n - 1] == 0) n--;
putbits(nbit, n);
i = 0;
while (i < n) {
k = pt_len[i++];
if (k <= 6) putbits(3, k);
else putbits(k - 3, (1U << (k - 3)) - 2);
if (i == i_special) {
while (i < 6 && pt_len[i] == 0) i++;
putbits(2, (i - 3) & 3);
}
}
}
void write_c_len(void)
{
int i, k, n, count;
n = NC;
while (n > 0 && c_len[n - 1] == 0) n--;
putbits(CBIT, n);
i = 0;
while (i < n) {
k = c_len[i++];
if (k == 0) {
count = 1;
while (i < n && c_len[i] == 0) { i++; count++; }
if (count <= 2) {
for (k = 0; k < count; k++)
putbits(pt_len[0], pt_code[0]);
} else if (count <= 18) {
putbits(pt_len[1], pt_code[1]);
putbits(4, count - 3);
} else if (count == 19) {
putbits(pt_len[0], pt_code[0]);
putbits(pt_len[1], pt_code[1]);
putbits(4, 15);
} else {
putbits(pt_len[2], pt_code[2]);
putbits(CBIT, count - 20);
}
} else putbits(pt_len[k + 2], pt_code[k + 2]);
}
}
void encode_c(int c)
{
putbits(c_len[c], c_code[c]);
}
void encode_p(uint p)
{
uint c, q;
c = 0; q = p; while (q) { q >>= 1; c++; }
putbits(pt_len[c], pt_code[c]);
if (c > 1) putbits(c - 1, p & (0xFFFFU >> (17 - c)));
}
void send_block(void)
{
uint i, k, flags, root, pos, size;
root = make_tree(NC, c_freq, c_len, c_code);
size = c_freq[root]; putbits(16, size);
if (root >= NC) {
count_t_freq();
root = make_tree(NT, t_freq, pt_len, pt_code);
if (root >= NT) {
write_pt_len(NT, TBIT, 3);
} else {
putbits(TBIT, 0); putbits(TBIT, root);
}
write_c_len();
} else {
putbits(TBIT, 0); putbits(TBIT, 0);
putbits(CBIT, 0); putbits(CBIT, root);
}
root = make_tree(NP, p_freq, pt_len, pt_code);
if (root >= NP) {
write_pt_len(NP, PBIT, -1);
} else {
putbits(PBIT, 0); putbits(PBIT, root);
}
pos = 0;
for (i = 0; i < size; i++) {
if (i % CHAR_BIT == 0) flags = buf[pos++]; else flags <<= 1;
if (flags & (1U << (CHAR_BIT - 1))) {
encode_c(buf[pos++] + (1U << CHAR_BIT));
k = buf[pos++] << CHAR_BIT; k += buf[pos++];
encode_p(k);
} else encode_c(buf[pos++]);
if (unpackable) return;
}
for (i = 0; i < NC; i++) c_freq[i] = 0;
for (i = 0; i < NP; i++) p_freq[i] = 0;
}
uint output_pos, output_mask;
#ifdef _lhufs_
extern void output5(uint c, uint p);
#else
void output5(uint c, uint p)
{
static uint cpos;
if ((output_mask >>= 1) == 0) {
output_mask = 1U << (CHAR_BIT - 1);
if (output_pos >= bufsiz - 3 * CHAR_BIT) {
send_block();
if (unpackable) return;
output_pos = 0;
}
cpos = output_pos++; buf[cpos] = 0;
}
buf[output_pos++] = (uchar) c; c_freq[c]++;
if (c >= (1U << CHAR_BIT)) {
buf[cpos] |= output_mask;
buf[output_pos++] = (uchar)(p >> CHAR_BIT);
buf[output_pos++] = (uchar) p;
c = 0; while (p) { p >>= 1; c++; }
p_freq[c]++;
}
}
#endif
void start_huf(void)
{
int i;
if (bufsiz == 0) {
bufsiz = 16 * 1024U;
while ((buf = malloc(bufsiz)) == NULL) {
bufsiz = (bufsiz / 10U) * 9U;
if (bufsiz < 4 * 1024U) error("Out of memory.");
}
}
buf[0] = 0;
for (i = 0; i < NC; i++) c_freq[i] = 0;
for (i = 0; i < NP; i++) p_freq[i] = 0;
output_pos = output_mask = 0;
init_putbits();
}
void end_huf(void)
{
if (! unpackable) {
send_block();
putbits(CHAR_BIT - 1, 0); /* flush remaining bits */
}
}
/***** decoding *****/
static void read_pt_len(int nn, int nbit, int i_special)
{
int i, c, n;
uint mask;
n = getbits(nbit);
if (n == 0) {
c = getbits(nbit);
for (i = 0; i < nn; i++) pt_len[i] = 0;
for (i = 0; i <